/**
 * 作为整个系统的网络请求库
 */
import { extend } from 'umi-request';
import axios from 'axios';

import { modalError } from 'utils/feedbacks';

// import {
//   // aes192CBCEncrypt,
//   // aes192CBCDecrypt,
//   // md5Encrypt,
// } from 'utils/cipher-handlers';

import moment from 'moment';

/**
 * 网络连接超时时间(ms)
 */
const NET_CONNECTION_TIME_OUT = 120 * 1000;

const codeMessageMap = {
  '404': '您访问的资源不存在',
  '500': '服务器发生错误，请联系管理员',
  '504': '网络连接超时，请重试'
};

/**
 * 网络异常处理(当状态码不为2XX时触发)
 * 一共分为两种类型的异常：网络异常，逻辑异常
 * 网络异常：弹框，不做任何处理
 * 逻辑异常：弹框，特殊 
 */
const _netErrorHandler = (error) => {
  const { code, msg } = error;

  // 业务数据异常，向上抛出
  if(!codeMessageMap[code]) throw { code, msg }; 

  // 如果是网络异常，直接弹框提示，不做任何处理
  modalError(msg);
};

const _commonNetRequestConfigs = {
  /** 超时时间(ms) **/
  timeout: NET_CONNECTION_TIME_OUT,
  /** 请求前缀 **/
  // prefix: ,
  /** 请求后缀 **/
  // suffix: '.html',
  /** 发送请求跨域 **/
  // credentials: 'include',
  /** 是否返回源response, 返回结果将包含一层 { data, response } **/
  getResponse: false,
  /** 'useCache' 是否使用缓存，当值为 true 时，GET 请求在 ttl 毫秒内将被缓存，缓存策略唯一 key 为 url + params 组合 **/
  useCache: false, // default
  /** 'ttl' 缓存时长（毫秒）， 0 为不过期 **/
  // ttl: 60000,
  /** 'maxCache' 最大缓存数， 0 为无限制 **/
  // maxCache: 0,
  /** 编码 **/
  charset: 'utf8',
  /** 异常处理 **/
  errorHandler: _netErrorHandler,
};

/**
 * 密文处理中间件处理程序
 */
// const _cipherHandlerMiddleware = async (ctx, next) => {
//   ctx.req.options.data = aes192CBCEncrypt(ctx.req.options.data)
//   await next()
//   ctx.res = aes192CBCDecrypt(ctx.res)
// };

/**
 * JSON处理中间件处理程序
 */
const _jsonHandlerMiddleware = async (ctx, next) => {
  ctx.req.options.data = JSON.stringify(ctx.req.options.data);
  await next();
  // 这里不用手动处理，系统自动解析为json
  // ctx.res = JSON.parse(ctx.res)
};

/**
 * 商户中间件
 */
// const _bizHandlerMiddleware = async (ctx, next) => {
//   ctx.req.options.data = { ...ctx.req.options.data, merchantNumber: MERCHANT_NUMBER };
//   await next();
// };

/**
 * 身份认证中间件
 */
// const _authHandlerMiddle = async (ctx, next) => {
//   // const { player } = window.g_app._store.getState();
//   // const { auth: { playerUserId, username, token } } = player;

//   // if (!playerUserId || !username || !token) {
//   //   throw { response: { 'status': 401 } };
//   // }

//   await next();
// };

/**
 * 签名中间件
 */
// const _signHandlerMiddleware = async (ctx, next) => {
//   let requestData = !ctx.req.options.data? {} : ctx.req.options.data;
  
//   const device = 'pc';
//   const timestamp = moment().unix();
//   const api = ctx.req.url;
//   const signature = md5Encrypt(`&${device}&${timestamp}&${api}`);

//   ctx.req.options.data = { ...requestData, playerUserId, device, timestamp, api, signature };

//   await next();
// };


/**
 * 普通的get请求
 */
export const GETRequest = (url, params) => {
  const request = extend({ ..._commonNetRequestConfigs });
  return request.get(url, { params });
};

/**
 * 普通需验证的get请求
 */
export const GETAuthedRequest = (jwt, url, params) => {
  // 构建request
  const request = extend({ 
    ..._commonNetRequestConfigs,
    // 叠加头部
    headers: {
      Authorization: `Bearer ${jwt}`,   // 将jwt按照一定规则放入头部
    }, 
  });

  // 构建拦截器，根据不同的响应码，做处理
  request.interceptors.response.use(async (response, options) => {
    const { status } = response;
    // 如果逻辑数据未正常响应，则不用处理响应码，直接返回
    if(status != 200) {
      const code = status;
      const msg = codeMessageMap[status];
      throw { code, msg };
    }
    else {
      const { code, msg } = await response.clone().json();
      // 逻辑数据正确返回
      if(code == 20000) return response;
      // 逻辑数据非正常返回
      throw { code, msg };
    }
  });

  return request.get(url, { params });
};

/**
 * 需验证的下载get请求
 */
export const GETDownloadAuthedRequest = (jwt, url, params) => {
  return axios.get(url, {
          params,
          // 叠加头部
          headers: {
            Authorization: `Bearer ${jwt}`,   // 将jwt按照一定规则放入头部
          },
          responseType: 'blob',
        })
        // 判断响应是否错误信息或者是文件
        .then((res) => {
          return new Promise((resolve, reject) => {
            const blob = res.data;
            const fileReader = new FileReader();
            fileReader.readAsText(blob, 'UTF-8');
            fileReader.onload = function() {
              try {
                const respJSON = JSON.parse(this.result);
                reject(respJSON);
              } 
              catch (error) {
                resolve(res);
              }
            };
          });
        })
        .then((res) => {
          // 1.构建文件名
          const fileName = decodeURI(res.headers["content-disposition"].split("filename=")[1]);
          // 2.构建文件a链接额下载href
          const fileBlob = new Blob([res.data]);
          const aElementHref = window.URL.createObjectURL(fileBlob);
          // 3.构建a链接
          let aElement = document.createElement('a');
          aElement.href = aElementHref;
          aElement.style.display = 'none';
          aElement.download = fileName;
          // 4.将a链接绑定到页面的dom
          document.body.appendChild(aElement);
          // 5.模拟点击a链接
          aElement.click();
          // 6.将a链接从页面的dom上移除
          document.body.removeChild(aElement);
          // 7.清除文件占用的浏览器内存
          window.URL.revokeObjectURL(aElementHref);
        })
        // 返回的状态码不是200
        .catch((err) => {
          throw err;
        });
}

/**
 * 普通的post请求
 */
export const POSTRequest = (url, params) => {
  const request = extend({ 
    ..._commonNetRequestConfigs,
    requestType: 'form',
  });

  // 构建拦截器，根据不同的响应码，做处理
  request.interceptors.response.use(async (response, options) => {
    const { status } = response;
    // 如果逻辑数据未正常响应，则不用处理响应码，直接返回
    if(status != 200) {
      const code = status;
      const msg = codeMessageMap[status];
      throw { code, msg };
    }
    else {
      const { code, msg } = await response.clone().json();
      // 逻辑数据正确返回
      if(code == 20000) return response;
      // 逻辑数据非正常返回
      throw { code, msg };
    }
  });

  return request.post(url, { data: params });
};

/**
 * 认证的post请求
 */
export const POSTAuthedRequest = (jwt, url, params) => {
  // 构建request
  const request = extend({ 
    ..._commonNetRequestConfigs, 
    method: 'POST',
    requestType: 'form',
    headers: {
      Authorization: `Bearer ${jwt}`,   // 将jwt按照一定规则放入头部
    }, 
  });
  
  // 构建拦截器，根据不同的响应码，做处理
  request.interceptors.response.use(async (response, options) => {
    const { status } = response;
    // 如果逻辑数据未正常响应，则不用处理响应码，直接返回
    if(status != 200) {
      const code = status;
      const msg = codeMessageMap[status];
      throw { code, msg };
    }
    else {
      const { code, msg } = await response.clone().json();
      // 逻辑数据正确返回
      if(code == 20000) return response;
      // 逻辑数据非正常返回
      throw { code, msg };
    }
  });
  
  return request.post(url, { data: params });
};

/**
 * 需验证的上传POST请求
 */
export const POSTUploadAuthedRequest = (jwt, url, file, params) => {
  const formData = new FormData();
  // 构建文件请求参数
  formData.append('file', file);
  // 构建其它请求参数
  for(let key in params) {
    formData.append(key, params[key]);
  }
  // 发送请求
  return axios.post(url, formData, {
    // 叠加头部
    headers: {
      'Authorization': `Bearer ${jwt}`,   // 将jwt按照一定规则放入头部
      'Content-Type': 'multipart/form-data',
    },
  })
  // 数据的解析
  .then((res) => {
    const { data: { code, msg, data } } = res;
    return Promise.resolve({ code, msg, data });
  })
  // 数据的处理
  .then(({ code, msg, data }) => {
    if (code == 20000) return { code, msg, data };
    // 如果上传失败
    if (code != 20000) return Promise.reject({ code, msg });
  })
  // 网络错误,服务端返回错误信息
  .catch((err) => {
    throw err;
  });
}

/**
 * 普通的PUT请求
 */
export const PUTRequest = (url, params) => {
  const request = extend({ 
    ..._commonNetRequestConfigs, 
    requestType: 'form',
  });
  return request.put(url, { data: params });
}

/**
 * 认证的put请求
 */
export const PUTAuthedRequest = (jwt, url, params) => {
  const request = extend({ 
    ..._commonNetRequestConfigs, 
    requestType: 'form',
    // 叠加头部
    headers: {
      Authorization: `Bearer ${jwt}`,   // 将jwt按照一定规则放入头部
    }, 
  });

  // 构建拦截器，根据不同的响应码，做处理
  request.interceptors.response.use(async (response, options) => {
    const { status } = response;
    // 如果逻辑数据未正常响应，则不用处理响应码，直接返回
    if(status != 200) {
      const code = status;
      const msg = codeMessageMap[status];
      throw { code, msg };
    }
    else {
      const { code, msg } = await response.clone().json();
      // 逻辑数据正确返回
      if(code == 20000) return response;
      // 逻辑数据非正常返回
      throw { code, msg };
    }
  });

  return request.put(url, { data: params });
}

/**
 * 普通的删除请求
 */
export const DELETERequest = (url, params) => {
  const request = extend({ ..._commonNetRequestConfigs });
  return request.delete(url, { params });
}

/**
 * 认证的删除请求
 */
export const DELETEAuthedRequest = (jwt, url, params) => {
  const request = extend({ 
    ..._commonNetRequestConfigs,
    // 叠加头部
    headers: {
      Authorization: `Bearer ${jwt}`,   // 将jwt按照一定规则放入头部
    }, 
  });

  // 构建拦截器，根据不同的响应码，做处理
  request.interceptors.response.use(async (response, options) => {
    const { status } = response;
    // 如果逻辑数据未正常响应，则不用处理响应码，直接返回
    if(status != 200) {
      const code = status;
      const msg = codeMessageMap[status];
      throw { code, msg };
    }
    else {
      const { code, msg } = await response.clone().json();
      // 逻辑数据正确返回
      if(code == 20000) return response;
      // 逻辑数据非正常返回
      throw { code, msg };
    }
  });

  return request.delete(url, { params });
}




/**
 * 带身份签名的post请求
 */
// export const postSignedRequest = (url, params) => {};

/**
 * 加密的post请求
 */
// export const postEncryptRequest = (url, json) => {
//   const request = extend({ ..._commonNetRequestConfigs, requestType: 'json' });
//   request.use(_bizHandlerMiddleware);
//   request.use(_jsonHandlerMiddleware);
//   // request.use(_cipherHandlerMiddleware);
//   return request.post(url, { data: json });
// };

/**
 * 带身份签名的加密post请求
 */
// export const postEncryptSignedRequest = (url, json) => {
//   const request = extend({ ..._commonNetRequestConfigs, requestType: 'json' })
//   request.use(_authHandlerMiddle);
//   request.use(_signHandlerMiddleware);
//   request.use(_bizHandlerMiddleware);
//   request.use(_jsonHandlerMiddleware);
//   // request.use(_cipherHandlerMiddleware)
//   return request.post(url, { data: json })
// };